package org.zhuzx.util;

import java.util.Comparator;
import java.util.concurrent.BlockingQueue;

/**
 * 优先级消费队列，按元素自然顺序或者传入的比较器排序，以决定出队次序（执行消费任务）。
 * @see org.zhuzx.util.AbstractConsumerQueue
 * @author zhuzx 2018年09月08日
 */
public abstract class AbstractPriorityConsumerQueue<E> extends AbstractConsumerQueue<E> {
	
	/**
	 * 构建优先级阻塞队列并启动基本数量的消费线程（常驻运行），需要元素自身实现Comparable接口。
	 */
	protected AbstractPriorityConsumerQueue() {
		this(DEFAULT_QUEUE_SIZE);
	}
	
	/**
	 * 构建优先级阻塞队列并启动基本数量的消费线程（常驻运行），需要元素自身实现Comparable接口。
	 * @param size 固定队列容量
	 */
	protected AbstractPriorityConsumerQueue(int size) {
		this(size, null);
	}
	
	/**
	 * 构建优先级阻塞队列并启动基本数量的消费线程（常驻运行）
	 * @param size 固定队列容量
	 * @param comparator 用来决定队列元素顺序的比较器
	 */
	protected AbstractPriorityConsumerQueue(int size, final Comparator<E> comparator) {
		Comparator<Runnable> comp = new Comparator<Runnable>() {
			@SuppressWarnings("unchecked")
			public int compare(Runnable o1, Runnable o2) {
				E e1 = ((Processor) o1).getElement();
				E e2 = ((Processor) o2).getElement();
				return comparator==null ? ((Comparable<E>)e1).compareTo(e2) : comparator.compare(e1, e2);
			}
		};
		BlockingQueue<Runnable> queue = new FixedPriorityBlockingQueue<>(size, comp);
		super.initExecutor(queue);
	}
	
	/**
	 * 将任务元素放入队列，若已满则阻塞，不返回false。<br>
	 * 但阻塞期间可能已将元素入队，具体阻塞逻辑依赖于队列类型。
	 * @see org.zhuzx.util.FixedPriorityBlockingQueue#put(E e)
	 */
	public boolean pushIntoQueue(final E element) {
		Runnable task = new Processor(element);
		return super.submitTask(task);
	}
	
	private class Processor implements Runnable {
		private E element;
		
		public Processor(E element) {
			this.element = element;
		}
		public void run() {
			process(this.element);
		}
		public E getElement() {
			return this.element;
		}
	}
	
}